package com.qiguliuxing.dts.db.service;

import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.qiguliuxing.dts.db.bean.CategorySellAmts;
import com.qiguliuxing.dts.db.bean.DayStatis;
import com.qiguliuxing.dts.db.dao.DtsOrderMapper;
import com.qiguliuxing.dts.db.dao.DtsRefundTraceMapper;
import com.qiguliuxing.dts.db.dao.ex.OrderMapper;
import com.qiguliuxing.dts.db.dao.ex.StatMapper;
import com.qiguliuxing.dts.db.domain.*;
import com.qiguliuxing.dts.db.util.OrderUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class DtsOrderService {
    @Resource
    private DtsOrderMapper dtsOrderMapper;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private StatMapper statMapper;
    @Resource
    private DtsRefundTraceMapper refundTraceMapper;

    public int add(DtsOrder order) {
        order.setAddTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        return dtsOrderMapper.insertSelective(order);
    }

    public int count(Integer userId) {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false);
        return (int) dtsOrderMapper.countByExample(example);
    }

    public DtsOrder findById(Integer orderId) {
        return dtsOrderMapper.selectByPrimaryKey(orderId);
    }

    public String getRandomNum(Integer num) {
        String base = "0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < num; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public int countByOrderSn(Integer userId, String orderSn) {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andUserIdEqualTo(userId).andOrderSnEqualTo(orderSn).andDeletedEqualTo(false);
        return (int) dtsOrderMapper.countByExample(example);
    }

    // TODO 这里应该产生一个唯一的订单，但是实际上这里仍然存在两个订单相同的可能性
    public String generateOrderSn(Integer userId) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        String now = df.format(LocalDate.now());
        String orderSn = now + getRandomNum(6);
        while (countByOrderSn(userId, orderSn) != 0) {
            orderSn = getRandomNum(6);
        }
        return orderSn;
    }

    public List<DtsOrder> queryByOrderStatus(Integer userId, List<Short> orderStatus, Integer page, Integer size) {
        DtsOrderExample example = new DtsOrderExample();
        example.setOrderByClause(DtsOrder.Column.addTime.desc());
        DtsOrderExample.Criteria criteria = example.or();
        criteria.andUserIdEqualTo(userId);
        if (orderStatus != null) {
            criteria.andOrderStatusIn(orderStatus);
        }
        criteria.andDeletedEqualTo(false);
        PageHelper.startPage(page, size);
        return dtsOrderMapper.selectByExample(example);
    }

    public List<DtsOrder> querySelective(Integer userId, String orderSn, String fetchCode, List<Short> orderStatusArray, Integer page,
                                         Integer size, String sort, String order) {
        DtsOrderExample example = new DtsOrderExample();
        DtsOrderExample.Criteria criteria = example.createCriteria();

        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (!StringUtils.isEmpty(orderSn)) {
            criteria.andOrderSnEqualTo(orderSn);
        }
        if (!StringUtils.isEmpty(fetchCode)) {
            criteria.andFetchCodeEqualTo(fetchCode);
        }
        if (orderStatusArray != null && orderStatusArray.size() != 0) {
            criteria.andOrderStatusIn(orderStatusArray);
        }
        criteria.andDeletedEqualTo(false);

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, size);
        return dtsOrderMapper.selectByExample(example);
    }

    public int updateWithOptimisticLocker(DtsOrder order) {
        LocalDateTime preUpdateTime = order.getUpdateTime();
        order.setUpdateTime(LocalDateTime.now());
        return orderMapper.updateWithOptimisticLocker(preUpdateTime, order);
    }

    public void deleteById(Integer id) {
        dtsOrderMapper.logicalDeleteByPrimaryKey(id);
    }

    public int count() {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andDeletedEqualTo(false);
        return (int) dtsOrderMapper.countByExample(example);
    }

    public List<DtsOrder> queryUnpaid() {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andOrderStatusEqualTo(OrderUtil.STATUS_CREATE).andDeletedEqualTo(false);
        return dtsOrderMapper.selectByExample(example);
    }

    public void finishOrder(List<String> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        dtsOrderMapper.finishOrder(list);
    }

    public List<DtsOrder> queryUnconfirm() {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andOrderStatusEqualTo(OrderUtil.STATUS_SHIP).andShipTimeIsNotNull().andDeletedEqualTo(false);
        return dtsOrderMapper.selectByExample(example);
    }

    public DtsOrder findBySn(String orderSn) {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andOrderSnEqualTo(orderSn).andDeletedEqualTo(false);
        return dtsOrderMapper.selectOneByExample(example);
    }

    public Map<Object, Object> orderInfo(Integer userId) {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false);
        List<DtsOrder> orders = dtsOrderMapper.selectByExampleSelective(example, DtsOrder.Column.orderStatus,
                DtsOrder.Column.comments);

        int unpaid = 0;
        int unship = 0;
        int unrecv = 0;
        int uncomment = 0;
        for (DtsOrder order : orders) {
            if (OrderUtil.isCreateStatus(order)) {
                unpaid++;
            } else if (OrderUtil.isPayStatus(order)) {
                unship++;
            } else if (OrderUtil.isShipStatus(order)) {
                unrecv++;
            } else if (OrderUtil.isConfirmStatus(order) || OrderUtil.isAutoConfirmStatus(order)) {
                uncomment += order.getComments();
            } else {
                // do nothing
            }
        }

        Map<Object, Object> orderInfo = new HashMap<Object, Object>();
        orderInfo.put("unpaid", unpaid);
        orderInfo.put("unship", unship);
        orderInfo.put("unrecv", unrecv);
        orderInfo.put("uncomment", uncomment);
        return orderInfo;
    }

    public List<DtsOrder> queryComment() {
        DtsOrderExample example = new DtsOrderExample();
        example.or().andCommentsGreaterThan((short) 0).andDeletedEqualTo(false);
        return dtsOrderMapper.selectByExample(example);
    }

    public List<DayStatis> recentCount(int statisDaysRang) {
        return statMapper.statisIncreaseOrderCnt(statisDaysRang);
    }

    public List<CategorySellAmts> categorySell() {
        return statMapper.categorySellStatis();
    }

    /**
     * 获取指定店铺的订单
     *
     * @param brandIds
     * @param userId
     * @param orderSn
     * @param orderStatusArray
     * @param page
     * @param size
     * @param sort
     * @param order
     * @return
     */
    public List<DtsOrder> queryBrandSelective(List<Integer> brandIds, Integer userId, String orderSn, String fetchCode,
                                              List<Short> orderStatusArray, Integer page, Integer size, String sort, String order) {

        String orderStatusSql = null;
        if (orderStatusArray != null) {
            orderStatusSql = "";
            for (Short orderStatus : orderStatusArray) {
                orderStatusSql += "," + orderStatus;
            }
            orderStatusSql = "and o.order_status in (" + orderStatusSql.substring(1) + ") ";
        }

        String orderBySql = null;
        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
            orderBySql = "o." + sort + " " + order;
        }

        String brandIdsSql = null;
        if (brandIds != null) {
            brandIdsSql = "";
            for (Integer brandId : brandIds) {
                brandIdsSql += "," + brandId;
            }
            brandIdsSql = " and g.brand_id in (" + brandIdsSql.substring(1) + ") ";
        }

        PageHelper.startPage(page, size);
        return orderMapper.selectBrandOrdersByExample(userId, orderSn, fetchCode, orderStatusSql, orderBySql, brandIdsSql);
    }

    /**
     * 对账管理
     *
     * @param brandIds
     * @param userId
     * @param orderSn
     * @param fetchCode
     * @param orderStatusArray
     * @param page
     * @param size
     * @param sort
     * @param order
     * @return
     */
    public List<DtsOrder> queryBrandSelectiveVerify(String startTime, String endTime, List<Integer> brandIds, Integer userId, Integer settlementFlag, String orderSn, String fetchCode,
                                                    List<Short> orderStatusArray, Integer page, Integer size, String sort, String order) {

        String orderStatusSql = null;
        if (orderStatusArray != null) {
            orderStatusSql = "";
            for (Short orderStatus : orderStatusArray) {
                orderStatusSql += "," + orderStatus;
            }
            orderStatusSql = "and o.order_status in (" + orderStatusSql.substring(1) + ") ";
        }

        String orderBySql = null;
        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
            orderBySql = "o." + sort + " " + order;
        }

        String brandIdsSql = null;
        if (brandIds != null) {
            brandIdsSql = "";
            for (Integer brandId : brandIds) {
                brandIdsSql += "," + brandId;
            }
            brandIdsSql = " and g.brand_id in (" + brandIdsSql.substring(1) + ") ";
        }

        PageHelper.startPage(page, size);
        return orderMapper.selectBrandOrdersByExampleVerify(startTime, endTime, brandIds, userId, orderSn, fetchCode, orderStatusSql, orderBySql, brandIdsSql);
    }

    /**
     * 对账管理
     *
     * @param userId
     * @param orderSn
     * @param fetchCode
     * @param orderStatusArray
     * @param page
     * @param size
     * @param sort
     * @param order
     * @return
     */
    public List<DtsOrder> querySelectiveVerify(String startTime, String endTime, Integer userId, Integer settlementFlag, String orderSn, String fetchCode, List<Short> orderStatusArray, Integer page,
                                               Integer size, String sort, String order) {
        DtsOrderRequest example = new DtsOrderRequest();
        example.setUserId(userId);
        example.setOrderSn(orderSn);
        example.setFetchCode(fetchCode);
        example.setOrderStatus(orderStatusArray);
        example.setDeleted(Boolean.FALSE);
        example.setSettlementFlag(settlementFlag);
        example.setStartTime(startTime);
        example.setEndTime(endTime);

        PageHelper.startPage(page, size);
        return dtsOrderMapper.selectByExampleVerify(example);
    }

    /**
     * 根据订单ID获取是否存在退货子订单
     *
     * @param orderId
     * @return
     */
    public Boolean hasRefundByOrderId(Integer orderId) {
        DtsRefundTraceExample example = new DtsRefundTraceExample();
        example.or().andDeletedEqualTo(false).andOrderIdEqualTo(orderId);
        if (refundTraceMapper.countByExample(example) > 0) {
            return true;
        } else {
            return false;
        }
    }

    //根据订单号看是否退款，退款已审核不展示
    public Boolean hasRefundByAudit(Integer orderId) {
        DtsRefundTraceExample example = new DtsRefundTraceExample();
        example.or().andDeletedEqualTo(false).andOrderIdEqualTo(orderId);
        DtsRefundTrace refundTrace = refundTraceMapper.selectOneByExample(example);
        //0 退款申请 1 退款审批通过 2 退款审批拒绝 3 退款完成
        if (Objects.nonNull(refundTrace) && (refundTrace.getStatus() == 0 || refundTrace.getStatus() == 1 || refundTrace.getStatus() == 2)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 根据查询类型获取赠予订单分页列表
     *
     * @param userId
     * @param giftType
     * @param page
     * @param size
     * @return
     */
    public List<DtsOrder> giftOrderlist(Integer userId, Integer giftType, Integer page, Integer size) {
        DtsOrderExample example = new DtsOrderExample();
        example.setOrderByClause(DtsOrder.Column.addTime.desc());
        DtsOrderExample.Criteria criteria = example.or();

        if (giftType.intValue() == 1) { //用户赠送的订单
            criteria.andCreateUserIdEqualTo(userId);
            criteria.andUserIdNotEqualTo(userId);
        } else { //用户接收的赠予订单
            criteria.andCreateUserIdNotEqualTo(userId);
            criteria.andUserIdEqualTo(userId);
        }
        criteria.andDeletedEqualTo(false);
        PageHelper.startPage(page, size);
        return dtsOrderMapper.selectByExample(example);
    }


    public List<Map<String, Object>> verifyAccounting(String startTime, String endTime, Integer brandId) {
        List<Map<String, Object>> result = new ArrayList();
        Set<Integer> setIds = new HashSet<>();
        Map<Integer, VerifyCountEntity> mapName = new HashMap<>();
        VerifyCountEntity entity = new VerifyCountEntity();
        entity.setStartTime(startTime);
        entity.setEndTime(endTime);
        entity.setBrandId(brandId);
        //已支付有效状态
        entity.setOrderStatusList(Lists.newArrayList(201, 301, 401, 402));
        //总额
        List<VerifyCountEntity> list1 = dtsOrderMapper.verifyCount(entity);
        common(setIds, mapName, list1);
        Map<Integer, VerifyCountEntity> map1 = commonMap(list1);

        //未结算
        entity.setSettlementFlag(1);
        //已支付有效状态
        List<VerifyCountEntity> list3 = dtsOrderMapper.verifyCount(entity);
        common(setIds, mapName, list3);
        Map<Integer, VerifyCountEntity> map3 = commonMap(list3);

        //已结算
        entity.setSettlementFlag(2);
        entity.setOrderStatusList(null);
        List<VerifyCountEntity> list2 = dtsOrderMapper.verifyCount(entity);
        common(setIds, mapName, list2);
        Map<Integer, VerifyCountEntity> map2 = commonMap(list2);

        //待结算
        entity.setSettlementFlag(1);
        entity.setOrderStatusList(Lists.newArrayList(401, 402));
        List<VerifyCountEntity> list4 = dtsOrderMapper.verifyCount(entity);
        common(setIds, mapName, list4);
        Map<Integer, VerifyCountEntity> map4 = commonMap(list4);
        setIds.stream().forEach(id -> {
            String brandName = mapName.get(id).getBrandName();
            Map<String, Object> map = new HashMap<>();
            map.put("brandId", id);
            map.put("brandName", brandName);
            String settlementMoney = "0";
            String actualPrice = "0";
            String alreadySettlement = "0";
            String noSettlement = "0";
            String waitSettlement = "0";
            if (Objects.nonNull(map1) && map1.containsKey(id)) {
                actualPrice = map1.get(id).getActualPrice();
                settlementMoney = map1.get(id).getSettlementMoney();
            }
            if (Objects.nonNull(map2) && map2.containsKey(id)) {
                alreadySettlement = map2.get(id).getActualPrice();
            }
            if (Objects.nonNull(map3) && map3.containsKey(id)) {
                noSettlement = map3.get(id).getActualPrice();
            }
            if (Objects.nonNull(map4) && map4.containsKey(id)) {
                waitSettlement = map4.get(id).getActualPrice();
            }
            map.put("settlementMoney", settlementMoney);
            map.put("actualPrice", actualPrice);
            map.put("alreadySettlement", alreadySettlement);
            map.put("noSettlement", noSettlement);
            map.put("waitSettlement", waitSettlement);
            result.add(map);
        });
        return result;
    }

    private Map<Integer, VerifyCountEntity> commonMap(List<VerifyCountEntity> list) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.stream().collect(Collectors.toMap(VerifyCountEntity::getBrandId, Function.identity()));
    }

    private void common(Set<Integer> setIds, Map<Integer, VerifyCountEntity> mapName, List<VerifyCountEntity> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.stream().forEach(x -> {
            mapName.put(x.getBrandId(), x);
            setIds.add(x.getBrandId());
        });
    }

}
